/*******************************************
 * Copyright 2007 Aphrodite Framework for javaME .
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Public License v2.0
 * which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * Email : owner@aphroditeme.dev.java.net
 * Contributors:
 *     Kent Elton - initial API and implementation
 *******************************************/

package com.aphrodite.io;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.Vector;

import javax.microedition.io.Connector;
import javax.microedition.io.file.FileConnection;
import javax.microedition.io.file.FileSystemRegistry;
import javax.microedition.lcdui.Image;

//import com.vernalis.util.logger.Logger;

/**
 * Simple API for File Connection operations
 * 
 * @author kentelt
 * 
 */
public class FileConnectionHelper {

	private String errorMessage;

	public boolean canWrite(String path) {
		// try{
		boolean writePer;
		try {
			FileConnection fc = (FileConnection) Connector.open(path);
			writePer = fc.canWrite();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			writePer = false;
		}
		System.out.println("[FileConnectionHelper.canWrite] write permission for path " + path + " " + writePer);
		return writePer;
	}

	public boolean createDirectory(String path, boolean isHidden) {

		try {
			// if (path.charAt(path.length() - 1) != '/') {
			// StringBuffer buf = new StringBuffer(path);
			// buf.insert(buf.length() - 1, '/');
			// path = buf.toString();
			// }
			FileConnection fc = (FileConnection) Connector.open(path);
			fc.mkdir();
			fc.setHidden(isHidden);
			fc.close();
			System.out.println("[FileConnectionHelper.createDirectory] creating directory in " + path);
			return true;
		} catch (SecurityException e) {
			errorMessage = e.toString();
			return false;
		} catch (IOException e) {
			errorMessage = e.toString();
			return false;
		}
	}

	public final void saveFile(InputStream is, int contentLen, String path) {
		byte[] data = new byte[contentLen];
		DataInputStream dis = new DataInputStream(is);
		try {
			dis.readFully(data);
			createFile(path, data);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public boolean createFile(final String path, final byte[] data) {
		try {
			System.out.println("[FileConnectionHelper.createFile] Creating file in path " + path);
			FileConnection fc = (FileConnection) Connector.open(path);
			fc.create();
			DataOutputStream dos = fc.openDataOutputStream();
			dos.write(data);
			dos.flush();
			dos.close();
			fc.close();
			System.out.println("[FileConnectionHelper.createFile] file created in path " + path);
			return true;
		} catch (SecurityException e) {
			errorMessage = e.toString();
			return false;
		} catch (IOException e) {
			System.out.println("[FileConnectionHelper] Error saving file the filesystem" + e.toString());
			errorMessage = e.toString();
			return false;
		}
	}

	public boolean deleteFile(String path) {

		try {
			FileConnection fc = (FileConnection) Connector.open(path);
			fc.delete();
			fc.close();
			return true;
		} catch (SecurityException e) {
			errorMessage = e.toString();
			return false;
		} catch (IOException e) {
			errorMessage = e.toString();
			return false;
		}

	}

	public String getErrorMessage() {
		return (errorMessage != null) ? errorMessage : "";
	}

	public long getFileSize(String path) {
		try {
			FileConnection fc = (FileConnection) Connector.open(path);
			return fc.fileSize();
		} catch (IOException e) {
			e.printStackTrace();
			return 0L;

		}
	}

	/**
	 * Returns free space on a path
	 * 
	 * @param drive
	 *            provide complete path (ie) file:///SDCard/ etc.
	 * @return int available space in KB, returns -1 if the operation has failed
	 */
	public int getFreeSpace(String drive) {
		int free = 0;
		try {
			FileConnection fc = (FileConnection) Connector.open(drive);
			free = (int) fc.availableSize() / 1024;
			fc.close();
		} catch (SecurityException se) {
			errorMessage = se.toString();
			free = -1;
		} catch (IOException e) {
			errorMessage = e.toString();
			e.printStackTrace();
			free = -1;
		}
		return free;
	}

	/**
	 * returns 0 if does not exist, 1 if exist and -1 if exception occured
	 * 
	 * @param path
	 * 
	 * @return int
	 */
	public int isExists(String path) {
		int ret = 0;
		try {
			FileConnection fc = (FileConnection) Connector.open(path);
			ret = (fc.exists()) ? 1 : 0;
			fc.close();
		} catch (SecurityException e) {
			// Logger.getLogger().logInfo(this.getClass(), "Security Exception "
			// + e.toString());
			errorMessage = e.toString();
			ret = -1;
		} catch (IOException e) {
			// Logger.getLogger().logInfo(this.getClass(), "I/O Exception " +
			// e.toString());
			errorMessage = e.toString();
			ret = -1;
		}
		return ret;
	}

	/**
	 * returns a vector containing the list of files/directories in a directory
	 * 
	 * @param path
	 * @return Vector
	 */
	public Vector listFiles(String path) {
		Vector vecFiles = new Vector();
		try {
			if (isExists(path) == 0) {
				createDirectory(path, true);
			}
			FileConnection fc = (FileConnection) Connector.open(path);
			Enumeration files = fc.list();
			while (files.hasMoreElements()) {
				// System.out.println((String) files.nextElement());
				vecFiles.addElement((String) files.nextElement());
			}
		} catch (SecurityException e) {
			errorMessage = e.toString();
		} catch (IOException e) {
			errorMessage = e.toString();
		}
		return vecFiles;
	}

	public InputStream readFile(String path) {
		try {
			FileConnection fc = (FileConnection) Connector.open(path);
			return fc.openInputStream();
		} catch (SecurityException e) {
			errorMessage = e.toString();
			return null;
		} catch (IOException e) {
			errorMessage = e.toString();
			return null;
		}
	}

	public byte[] readFileAsBin(String path) {
		InputStream is = readFile(path);
		int len = (int) getFileSize(path);
		byte[] data = new byte[len];
		DataInputStream dis = new DataInputStream(is);
		try {
			dis.readFully(data);
		} catch (IOException e) {
			e.printStackTrace();
			return null;
		}
		return data;
	}

	/**
	 * Slower compared to the other method
	 * 
	 * @return
	 */
	public Image readImageAsBin(String path) {
		byte[] data = readFileAsBin(path);
		return Image.createImage(data, 0, data.length);

	}

	public javax.microedition.lcdui.Image readImage(String path) {
		try {
			return javax.microedition.lcdui.Image.createImage(readFile(path));
		} catch (IOException e) {
			System.out.println("[FileConnectionHelper] Error reading image from the filesystem" + e.toString());
			return null;
		}

	}

	/**
	 * 
	 * @return
	 */
	public Vector getDrives() {
		// try {
		Vector drive = new Vector();
		Enumeration drives = FileSystemRegistry.listRoots();
		while (drives.hasMoreElements()) {
			drive.addElement((String) drives.nextElement().toString());

		}
		return drive;
		// } catch (java.io.IOException e) {
		// return null;
		// }
	}
}
